﻿"""
获取上传的ini配置文件的位置信息，并将标准件的电压，电流写进新的配置文件
"""
import os
import shutil
import pyodbc
# 导入自制模块
from sortingdataprocess import *
from setiniconfig import *
from getcobspec import *


def config_precal(form1_infos, machine_label, cnxn, logger, CCT, CCT_String):
    """
    步骤一的参数说明
    :param form1_infos:  步骤一的字典数据：工单号、标准件型号、机台号、工号、临时文件路径、上传的配置文件名称
    :param cnxn: 权限高的数据库连接（用于更新、修改等）
    :param logger: 整个flask的日志记录器
    :param CCT: 双色温区分标志：low/high;低色温/正常 均使用low,高色温 使用high
    :param CCT_String: 色温字符串，用于查询双色温对应标准件数据
    :return:
    """
    '''
    1 进行查询,数据库中工单号对应的标准件与输入标准件型号是否对应,CF2,CF3是否有效
    2 查询标准件是否存在有效数据
    3 查询工单的lotID在数据库中是否存在,存在+1,不存在设置为1
    4 创建上传文件路径,并读取上传的配置文件进行电流.电压的修改
    5 将form1_infos中的数据,存入数据库的Precal_Info1中
    '''
    # 定义返回值，排除未定以返回值时程序报错
    flash_result = {}
    initconf_path = None
    lotID = None

    # 定义数据库连接的游标
    cursor = cnxn.cursor()
    # 启用快速查询
    cursor.fast_executemany = True

    # 根据单号查询品号
    item_code = get_item_code(form1_infos['MoID'])

    # 调用getcobspec中定义的get_cf函数,根据CCT的值分类,获得cf的值
    if item_code:
        if not CCT:
            CF2_pars = get_cf(item_code, 2)
            CF3_pars = get_cf(item_code, 3)
        else:
            CF2_pars = get_cf(item_code, 2, CCT)
            CF3_pars = get_cf(item_code, 3, CCT)
    else:
        CF2_pars = pd.DataFrame()
        CF3_pars = pd.DataFrame()

    # CG产品增加获取工单、标准件温度步骤,不是CG产品的返回0
    if form1_infos['StandardPartID'].startswith('CG'):
        # 获取工单对应的温度
        temper_1 = get_cold_or_hot(form1_infos['MoID'])
        # 获取标准件对应温度
        temper_2 = get_Temperture(form1_infos['StandardPartID'], CCT_String)
    else:
        temper_1, temper_2 = 0, 0

    # 补粉校准时检查标准件上次更新时间，对'过期'进行验证;分光时跳过
    # days = get_days(form1_infos['StandardPartID'])
    # df_special = pd.read_excel("ini/型号.xlsx", header=0)
    # list_model = list(df_special['StandardpartID'])

    # 定义sql语句,进行工单与标准件型号的验证
    cursor.execute(
        "SELECT  T1.DOC_NO,T2.ITEM_CODE,T2.ITEM_NAME,T2.FEATURE_NAME,T2.FEATURE_VALUE_DESC FROM MO_ITEM as T1,"
        "ITEM_CODE_VALUE as T2 WHERE T1.ITEM_CODE=T2.ITEM_CODE "
        f"AND T1.DOC_NO='{form1_infos['MoID']}' AND FEATURE_VALUE_DESC='{form1_infos['StandardPartID']}';")
    rows = cursor.fetchall()

    # 根据预先定义的标准，找到对应的椭圆标准
    if not CCT:
        df_color = get_color_stand(item_code)
        df_color_5 = get_color_stand_5(item_code)
    else:
        df_color = get_color_stand(item_code, CCT)
        df_color_5 = get_color_stand_5(item_code, CCT)

    # 椭圆标准每个值的验证,不存在空值
    flag1 = False
    if not df_color.empty:
        for i in df_color.itertuples():
            for column in ['CIEx', 'CIEy', 'a', 'b', 'θ']:
                # 判断颜色标准是否含有空值
                if getattr(i, column) is None or pd.isna(getattr(i, column)):
                    flag1 = True
    flag2 = False
    if not df_color_5.empty:
        for i in df_color_5.itertuples():
            for column in ['ID']:
                # 判断颜色标准是否含有空值
                if getattr(i, column) is None or pd.isna(getattr(i, column)):
                    flag2 = True

    # 获取标准件类型，一般来说标准件有效数据类型一致且唯一
    type = get_standardPart_type(form1_infos['StandardPartID'], CCT_String)

    # 情况1：工单号错误，未找到对应品号
    if not item_code:
        flash_result[1] = f'{machine_label}<br>工单未找到对应品号,请检查工单号是否输入错误！'
        logger.warn(f"{form1_infos['MachineID']}号设备,工单{form1_infos['MoID']}未找到对应品号")
    # 情况2：工单号与标准件不对应
    elif not rows:
        flash_result[2] = f'{machine_label}<br>工单与标准件不对应,请检查工单号是否输入错误或标准件是否拿错！'
        logger.warn(f"{form1_infos['MachineID']}号设备,工单标准件不对应")
    # 情况3：标准件类型缺失
    elif type.empty:
        flash_result[3] = f'{machine_label}<br>标准件类型缺失,请交由实验室更新！'
        logger.warn(f"{form1_infos['StandardPartID']}-标准件不存在类型")
    # 情况4：标准件类型不唯一
    elif len(set(type['StandardPart_Type'])) != 1:
        flash_result[4] = f'{machine_label}<br>标准件类型不唯一,请交由实验室更新！'
        logger.warn(f"{form1_infos['StandardPartID']}-标准件存在两种有效类型")
    # 情况5：一次性标准件进行工单号的验证
    elif '一次性' in list(type['StandardPart_Type']) and form1_infos['MoID'] not in list(type['MoID'])[0]:
        flash_result[5] = f'{machine_label}<br>' \
                          f'一次性工单与标准件不对应,请先检查工单号是否输入错误或标准件是否拿错！<br>确认无误后,请交由实验室更新！'
        logger.warn(f"{form1_infos['MachineID']}号设备,工单号与一次性标准件不对应")
    # 情况6：CF2系数不存在
    elif CF2_pars.empty:
        flash_result[6] = f"{machine_label}<br>该工单没有CF2系数,请联系研发进行数据库表更新！"
        logger.warn(f"{form1_infos['MachineID']}号设备,工单:{form1_infos['MoID']}没有CF2系数")
    # 情况7：CF3系数不存在
    elif CF3_pars.empty:
        flash_result[7] = f"{machine_label}<br>该工单没有CF3系数，请联系研发进行数据库表更新！"
        logger.warn(f"{form1_infos['MachineID']}号设备,工单:{form1_infos['MoID']}没有CF3系数")
    # 情况8：电压没有有效值
    elif get_spec_range(item_code).query("Parameter == 'ForwardVoltage_V'").empty:
        flash_result[8] = f"{machine_label}<br>SpecRange表格无有效电压范围数据,请联系研发进行数据库表更新！"
        logger.warn(f"{form1_infos['MachineID']}号设备,SpecRange表格无有效电压范围数据")
    # 情况9：CG产品冷热太不对应
    elif form1_infos['StandardPartID'].startswith('CG') and (
            not temper_1 or not temper_2 or abs(float(temper_1) - float(temper_2)) > 10):
        flash_result[9] = f"{machine_label}<br>标准件冷热态不对应工单,请交由实验室更新！"
        logger.warn(f"{form1_infos['MachineID']}号设备,标准件{form1_infos['StandardPartID']}冷热态不对应工单")

    # 该标准件不在分光中
    # elif days is None and get_flag(form1_infos['StandardPartID']):
    #     flash_result[7] = "标准件无有效数据"
    # elif form1_infos['StandardPartID'] not in list_model and days > 20 and get_flag(form1_infos['StandardPartID']):
    #     flash_result[8] = "该标准件已过期，请联系实验室进行更新"
    # elif form1_infos['StandardPartID'] in list_model and days > 10 and get_flag(form1_infos['StandardPartID']):
    #     flash_result[9] = "该标准件已过期，请联系实验室进行更新"
    # 其他情况
    else:
        # 根据CCT，查询不同色温对应的标准件数据
        if CCT:
            # 查询标准件数据是否存在有效数据,并且电压为标准件最大值基础上+5
            cursor.execute("SELECT StandardPartID,AVG(Current_mA), MAX(ForwardVoltage_V)+5 FROM StandardPartData "
                           f"WHERE StandardPartID='{form1_infos['StandardPartID']}{CCT_String}' "
                           f"and DataStatus=1 GROUP by StandardPartID")
        else:
            cursor.execute("SELECT StandardPartID,AVG(Current_mA), MAX(ForwardVoltage_V)+5 FROM StandardPartData "
                           f"WHERE StandardPartID='{form1_infos['StandardPartID']}' "
                           f"and DataStatus=1 GROUP by StandardPartID")
        rows = cursor.fetchall()
        # 情况10：标准件无有效的对应数据
        if not rows:
            flash_result[10] = f'{machine_label}<br>标准件没有有效数据,交由实验室进行更新！'
            logger.warn(
                f"{form1_infos['MachineID']}号设备,标准件-{form1_infos['StandardPartID']};工单-{form1_infos['MoID']}不对应")
            return flash_result, initconf_path, lotID
        else:
            # 查询到电压、电流
            current = rows[0][1]
            voltage = rows[0][2]
            # 日志记录步骤一关键信息
            logger.info(f"{form1_infos['MachineID']}号设备使用电流：{current}, 电压：{voltage}\n"
                        f"标准件名称：{form1_infos['StandardPartID']},工单号：{form1_infos['MoID']}")
            # 查询对于工单的LOTID是否存在，存在+1，不存在初始化为1
            cursor.execute(
                f"SELECT MAX(LOTID) FROM Precal_Info1 WHERE MOID='{form1_infos['MoID']}';")
            rows = cursor.fetchall()
            if rows[0][0] is None:
                lotID = 1
            else:
                lotID = rows[0][0] + 1
            # 添加LotID到form1_infos字典中
            form1_infos['LotID'] = lotID

            # 创建上传与下载目录并添加到列表
            uploadsDir = os.path.join('uploads', 'position', str(datetime.now().year), str(datetime.now().month))
            # 不存在上传目录，进行创建
            if not os.path.exists(uploadsDir):
                os.makedirs(uploadsDir)
            downloadsDir = os.path.join('downloads', 'initconf', str(datetime.now().year), str(datetime.now().month))
            # 不存在下载目录，进行创建
            if not os.path.exists(downloadsDir):
                os.makedirs(downloadsDir)

            # 获得文件后缀名
            ext = os.path.splitext(form1_infos['temp_path'])[1]
            # 新生成文件名：'position-' + 工单号 + '-' + 批次号 + 文件后缀
            upnew_filename = 'position-' + form1_infos['MoID'] + '-' + str(lotID) + ext
            # 拼接上传目录，将上传路径添加进form1_infos字典中
            form1_infos['UploadPath'] = os.path.join(uploadsDir, upnew_filename)
            # 复制文件内容
            shutil.copy(form1_infos['temp_path'], form1_infos['UploadPath'])

            try:
                # 读取初始化配置文件
                # 单颗
                if form1_infos['MachineID'] == 4:
                    # 情况11：椭圆数据缺失
                    if flag1:
                        flash_result[11] = f"{machine_label}<br>" \
                                           f"Color_Standard表格无有效颜色标准数据,请联系研发进行数据库表更新！"
                        logger.warn(f"{form1_infos['MachineID']}号设备,Color_Standard表格无有效颜色标准数据")
                    else:
                        # 读取服务器原始配置文件
                        ini_file_read(r'.\ini\init4.ini')
                        # 读取上传的位置配置文件
                        position_file_read(form1_infos['UploadPath'])
                        # 进行位置配置部分的替换
                        set_position_5()
                        # 修改配置文件的电流电压
                        set_voltage_current_4(voltage, current)
                        # 设置颜色标准
                        set_color_stand_4(df_color)
                # 中普连片
                elif form1_infos['MachineID'] == 3:
                    # 情况11：椭圆数据缺失
                    if flag1:
                        flash_result[5] = f"{machine_label}<br>" \
                                          f"Color_Standard表格无有效颜色标准数据,请联系研发进行数据库表更新！"
                        logger.warn(f"{form1_infos['MachineID']}号设备,Color_Standard表格无有效颜色标准数据")
                    else:
                        # 读取服务器原始配置文件
                        ini_file_read(r'.\ini\init3.ini')
                        # 修改配置文件的电流电压
                        set_voltage_current(voltage, current)
                        # 设置颜色标准
                        set_color_stand(df_color)
                # 一体
                elif form1_infos['MachineID'] == 5 or form1_infos['MachineID'] == 22:
                    # 情况11：椭圆数据缺失
                    if flag2:
                        flash_result[5] = f"{machine_label}<br>" \
                                          f"Color_Standard表格无有效颜色标准数据,请联系研发进行数据库表更新！"
                        logger.warn(f"{form1_infos['MachineID']}号设备,Color_Standard表格无有效颜色标准数据")
                    else:
                        # 读取服务器原始配置文件
                        ini_file_read(r'.\ini\init5.ini')
                        # 读取上传的配置文件
                        position_file_read(form1_infos['UploadPath'])
                        # 移除position,clamp章节,读取上传配置文件的position和clamp章节并赋值给初始化配置文件
                        set_position_5()
                        # 修改配置文件的电流电压
                        set_voltage_current_4(voltage, current)
                        # 设置颜色标准
                        set_color_stand_5(df_color_5)
                # 根据CCT，将下载出来的配置文件添加 高低色温提示
                if CCT:
                    str1 = '-低色温' if CCT == 'low' else '-高色温'
                    down_filename = '配置-' + form1_infos['MoID'] + '-' + str(lotID) + str1 + '.ini'
                else:
                    down_filename = '配置-' + form1_infos['MoID'] + '-' + str(lotID) + '.ini'
                # 步骤一下载文件路径设置
                initconf_path = os.path.join(downloadsDir, down_filename)
                # 保存在 生成 的路径
                ini_file_save(initconf_path)
                # 将路径添加进form1_infos字典中
                form1_infos['DownloadPath'] = initconf_path

                # 删除字典temp_path及临时文件
                os.remove(form1_infos.pop('temp_path'))
            except Exception as e:
                flash_result[404] = f'{machine_label}<br>' \
                                    f'配置文件生成过程中出现错误,截图反馈至实验室<br>问题描述:{e}'
                logger.error(f"未定义的错误发生！问题描述:{e}")
            else:
                # 成功完成配置文件之后,进行数据库存储
                # 插入当前时间
                form1_infos['UpdateTime'] = str(datetime.now())
                # 遍历字典
                kvs = [(k, v) for k, v in form1_infos.items() if v is not None]
                # 创建sql语句
                sql_data = f"INSERT INTO Precal_Info1({','.join(i[0] for i in kvs)}) " \
                           f"VALUES ({','.join(repr(i[1]) for i in kvs)});"
                try:
                    cursor.execute(sql_data)
                    cnxn.commit()
                except pyodbc.OperationalError:
                    flash_result[100] = f'{machine_label}<br>' \
                                        f'数据库连接断开!请关闭网页后,重新进行校准'
                    logger.error(f"数据库连接断开!")
                except pyodbc.InterfaceError:
                    flash_result[100] = f'{machine_label}<br>' \
                                        f'数据库登陆失败!请关闭网页后,重新进行校准'
                    logger.error(f"数据库登陆失败!")
                except Exception as e:
                    flash_result[404] = f'{machine_label}<br>' \
                                        f'第一步数据库存储时发生错误,截图反馈至实验室<br>问题描述:{e}'
                    logger.error(f"数据库Precal_Info1表插入失败，问题描述:{e}")
                else:
                    flash_result['成功'] = '配置生成成功'
                    logger.info(f"{form1_infos['MachineID']}号设备, {form1_infos['MoID']}配置生成成功-{initconf_path}")
    return flash_result, initconf_path, lotID


if __name__ == '__main__':
    # mo_id = '5101-20060005'
    # standard_part = 'MY2148-033-1210-M3080'
    # mo_id = '5101-20040024'
    # standard_part = 'L2128-007-0702-R3080'
    form1_infos = {'MoID': '5101-20060005', 'MachineID': 0, 'UserID': '10223', 'ProcessID': '1',
                   'StandardPartID': 'MY2148-033-1210-M3080',
                   'temp_path': 'uploads\\temp\\input.ini',
                   'UploadOriginalFileName': 'init00.ini'}
    print(config_precal(form1_infos))
